/*
 * @ author madman
 * @ use 公用类
 */
const jwt = require('jsonwebtoken')
const mongoose = require('mongoose');
const moment = require('moment');
const crypto = require('crypto')
import fs from 'fs';
const SystemModel = require('../../models/system/system.model');
class Utils {
    constructor() {
        this.limt = 10; //分页条数
    }
    //分页静态方法
    /*
     * @options.name              模型路径
     * @options.type              page:分页类型|pop:关联类型|list:列表类型
     * @options.findField         查询字段
     * @options.queryField        过滤字段
     * @options.populate          关联字段
     * @options.populateField     关联过滤字段
     * @options.sortType          排序类型
     * @options.sortVal           排序字段
     * @options.limt              分页数
     */
    async _Page(ctx, options) {
        const moduleName = require(`../../models/${options.name}.model`);
        const pagingParams = { __v: 0 }
        const _findField = options.findField || {}
        const _sort = {}
        let result
        const filterField = { ...pagingParams, ...options.queryField }
        const populateField = options.populateField || ''
        _sort[options.sortType || 'createdAt'] = options.sortVal || -1
        if (options.type === 'page' || options.type === 'pop') {
            // const total = await moduleName.find(_findField).count()  // count方法查询总数有问题，下次aggregate方法
            let total =  await moduleName.aggregate([{
                $match: {
                    $and: [_findField],
                }
            }, {
                $group : {  
                   _id : null,  
                   count: { $sum: 1 }  
                }  
              }  
            ])
            let $total = (total.length > 0 && total[0].count) || 0   // 聚合查询出来的是数组，查不到数据会返回空数组，需要进行判断
            const limt = parseInt(options.limt) || this.limt
            const curPage = parseInt(ctx.query.page) - 1 || 0
            if (options.type === 'pop') {
                result = await moduleName.find(_findField, filterField)
                    .limit(limt)
                    .skip(limt * curPage)
                    .sort(_sort)
                    .populate(options.populate, populateField)
            } else {
                result = await moduleName.find(_findField, filterField)
                    .limit(limt)
                    .skip(limt * curPage)
                    .sort(_sort)
            }
            if (result) {
                return await {
                    data: result,
                    total: $total,
                    pages: Math.ceil($total / limt)
                }
            }
        } else {
            result = await moduleName.find(_findField, filterField).sort(_sort)
            if (result) {
                return await {
                    data: result
                }
            }
        }

    }
    /*
     * 获取列表分页方法
     * @modelName  传入模型路径
     */
    async getPageList(ctx, modelName) {
        let result = await this._Page(ctx, modelName)
        if (result) {
            return {
                result: result.data,
                total: result.total,
                pages: result.pages
            }
        }
    }
    //生成token
    async createToken(name) {
        const token = jwt.sign({
            name: name
        }, 'secret', { expiresIn: '86400000' });
        return await token;
    }
    //判断token是否有效
    async checkToken(ctx, next) {
        let token = ctx.query.token || ctx.request.token || ctx.cookies.get('token')
        let decoded = jwt.decode(token, 'secret')
        // 监测 token 是否过期
        if (token && decoded && (decoded.exp <= Date.now() / 1000)) {
            return ctx.error({
                code: 401,
                message: 'token过期，请重新登录'
            })
        }
        await next();
    }
    //文件上传类
    async createUpload(ctx) {
        const { files, mid, file } = ctx.upload;
        console.log(ctx.upload)
        if (!files || !file) return ctx.error({ msg: '上传失败!' });
        return ctx.success({ msg: '上传成功!', data: { mid, files, file } });
    }
    // 订单号生成
    order_sn_create() {
        const _data = moment(new Date()).format("YYYY") + moment(new Date()).format("MM") + moment(new Date()).format("DD")
        const _random = parseInt(new Date().getTime() * Math.random())
        return _data + _random.toString().substr(1, 10);
    }
    // 格式化提交过来的字段，可用于单个字段更新
    _params(_paramsBody, type) {
        const paramsBody = [_paramsBody]
        const _params = {}
        paramsBody.forEach((item) => {
            console.log(item)
            Object.keys(item).forEach((_item) => {
                if (typeof _paramsBody[_item] === 'boolean' || _paramsBody[_item] || _paramsBody[_item] === '') {
                    _params[_item] = _paramsBody[_item]
                }
            })
        })
        return _params
    }
    //微信回调中转页
    wexin_redirect_url(ctx) {
        const redirect_uri = ctx.query.redirect_url
        ctx.redirect(redirect_uri + '?code=' + ctx.query.code + '&state=' + ctx.query.state)
    }
    //获取当前时间前7天的日期
    getDay(day) {
        var today = new Date();
        var targetday_milliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day;
        today.setTime(targetday_milliseconds); //注意，这行是关键代码
        var tYear = today.getFullYear();
        var tMonth = today.getMonth();
        var tDate = today.getDate();
        tMonth = this.doHandleMonth(tMonth + 1);
        tDate = this.doHandleMonth(tDate);
        return tYear + "-" + tMonth + "-" + tDate;
    }
    doHandleMonth(month) {
        var m = month;
        if (month.toString().length == 1) {
            m = "0" + month;
        }
        return m;
    }
    // 获取当前时间前7天的数组
    get7dayArr() {
        let now = new Date();
        const s = [];
        let i = 0;
        while (i < 7) {
            let Day = now.getDate() < 10 ? '0' + now.getDate() : now.getDate()
            let Month = (now.getMonth() + 1) < 10 ? '0' + (now.getMonth() + 1) : (now.getMonth() + 1)
            s.push({ _id: now.getFullYear() + '-' + Month + '-' + Day, total: 0 });
            now = new Date(now - 24 * 60 * 60 * 1000);
            i++
        }
        return s
    }
    //数组对象去重
    getArrReduce(arr) {
        const allArr = []
        for (let i = 0; i < arr.length; i++) {　　
            let flag = true;　　
            for (var j = 0; j < allArr.length; j++) {　　　　
                if (arr[i]._id == allArr[j]._id) {　　　　　　
                    flag = false;
                };　　
            };　　
            if (flag) {
                allArr.push(arr[i]);　　
            };
        };
        return allArr.sort(this.sortArr('_id'))
    }
    //对数组对象进行排序
    sortArr(prop) {
        return function(obj1, obj2) {
            var val1 = obj1[prop];
            var val2 = obj2[prop];
            if (val1 < val2) {
                return -1;
            } else if (val1 > val2) {
                return 1;
            } else {
                return 0;
            }
        }
    }
    //合并数组 
    concatArr(arr) {
        const total = arr.map(item => {
            return item.total
        })
        const time = arr.map(item => {
            return item._id
        })
        return {
            total: total,
            time: time
        }
    }
    //加密
    cipher(str, secret) {
        var cipher = crypto.createCipher('aes192', secret);
        var enc = cipher.update(str, 'utf8', 'hex');
        enc += cipher.final('hex');
        return enc;
    }
    //解密
    decipher(str, secret) {
        var decipher = crypto.createDecipher('aes192', secret);
        var dec = decipher.update(str, 'hex', 'utf8');
        dec += decipher.final('utf8');
        return dec;
    }
    //解密UID返回OPENID
    decipherOpenid(ctx) {
        let uid = ctx.cookies.get('uid')
        if (uid) {
            const decipherOpenid = this.decipher(uid, "openid")
            const openid = decipherOpenid.split(',')[0]
            return openid;
        } else {
            return false
        }
    }
    // 写入目录
    mkdirsSync(dirname){
        if (fs.existsSync(dirname)) {
          return true
        } else {
          if (this.mkdirsSync(path.dirname(dirname))) {
           fs.mkdirSync(dirname)
           return true
          }
        }
        return false
    }
    //获取应用的基本参数
   async getPrameter() {
        return await SystemModel.findOne({ _id: 'SYS' })
    }
}

export default new Utils;
